package cn.edu.sjtu.spinning.service.impl;

import cn.edu.sjtu.spinning.domain.Task;
import cn.edu.sjtu.spinning.dto.StateResponse;
import cn.edu.sjtu.spinning.dto.TaskInput;
import cn.edu.sjtu.spinning.enums.DeviceStatus;
import cn.edu.sjtu.spinning.enums.TaskStatus;
import cn.edu.sjtu.spinning.global.ExecuteTask;
import cn.edu.sjtu.spinning.service.SpinningService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;

@Slf4j
@Service("WithoutDevice")
public class SpinningMockServiceImpl implements SpinningService {

  private Queue<Task> taskQueue = new LinkedBlockingQueue<>();

  private final ExecuteTask executeTask;

  public SpinningMockServiceImpl(ExecuteTask executeTask) {
    this.executeTask = executeTask;
  }

  @Override
  public StateResponse queryECNState() {
    return StateResponse.ofECNState(executeTask.getDeviceStatus());
  }

  @Override
  public StateResponse queryTaskState(String processId, String taskId) {
    String key = processId.concat(taskId);
    Map<String, Task> taskMap = executeTask.getTaskMap();
    Task task = taskMap.get(key);
    if (task != null) {
      StateResponse stateResponse = StateResponse.ofTaskState(task);
      if (task.getStatus() == TaskStatus.PENDING) {
        return StateResponse.ofTaskPendingState();
      } else if (task.getStatus() == TaskStatus.DONE) {
        //        taskMap.remove(key);
      }
      return stateResponse;
    }
    return null;
  }

  // start
  @Override
  public boolean addTaskToQueue(TaskInput taskInput) {
    Task task = new Task();
    BeanUtils.copyProperties(taskInput, task);
    task.setStatus(TaskStatus.PENDING);
    task.setReleaseTime(new Date());
    String key = task.getProcessId().concat(task.getTaskId());
    executeTask.getTaskMap().put(key, task);
    return taskQueue.offer(task);
  }

  @Scheduled(fixedRate = 2000)
  public void executeTask() {
    // ready 才 poll , busy 不 poll
    if (!taskQueue.isEmpty() && executeTask.getDeviceStatus() == DeviceStatus.READY) {
      Task task = taskQueue.poll();
      executeTask.executeTask(task);
    }
    Task currentTask = executeTask.getCurrentTask();
    if (currentTask != null) {
      log.info("当前执行的任务为: {}, 状态是: {}", currentTask.getTaskId(), executeTask.getDeviceStatus());
    }
    log.info(
        "已执行队列为: {}, 当前任务:{},  当前状态{}",
        executeTask.getTaskMap(),
        currentTask,
        executeTask.getDeviceStatus());
  }

  @Override
  public Map<Integer, List<Task>> retTasksPool() {
    return executeTask.getTaskMap().values().stream()
        .collect(
            Collectors.groupingBy(
                item -> item.getStatus().ordinal(), LinkedHashMap::new, Collectors.toList()));
  }
}
